package inno.specificCrossover;

import inno.treeRepro.Chromosome;
import inno.treeRepro.Node;

import java.util.ArrayList;
import java.util.HashMap;

public class DummyCrossover implements Crossover{
	private HashMap<Integer, ArrayList<Node>> newTreeMap = new HashMap<Integer, ArrayList<Node>>(); // this is a  hash map of the tree far fast approch where each key is the level and the values
	private HashMap<Integer,Boolean> newTreeLevels = new HashMap<Integer, Boolean>(); // this is a  hash map of the tree far fast approch where each key is the level and the values

	public ArrayList<Chromosome> doCrossover(Chromosome subject1, Chromosome subject2){
		HashMap<Integer, ArrayList<Node>> chromeHash1 = subject1.getDfsMap();
		HashMap<Integer, ArrayList<Node>> chromeHash2 = subject2.getDfsMap();
		while (1<2) // make a loop until we get the right numbers
		{
			int randLevel1 = (int) Math.round(Math.random()*(chromeHash1.size()-1)); // choose the place where we want to do the mutation
			int randLevel2 = (int) Math.round(Math.random()*(chromeHash2.size()-1)); // choose the place where we want to do the mutation
			//System.out.println(randLevel1+","+randLevel2);
			HashMap<Integer, ArrayList<Node>> tempArrayLevel = subject1.getTreeLevels();
			ArrayList<Node> pass=tempArrayLevel.get(randLevel1);
			if (chromeHash1.size()==1){	// means the chrom is a one level tree so we just return him
				ArrayList<Chromosome> tempArray = new ArrayList<Chromosome>();
				tempArray.add(subject1);
				return tempArray;
			}
			if (chromeHash1.size()==2){ // means that the chrom is a two level tree
				if (tempArrayLevel.get(0)==null) { // this means that we have a one level tree with only one son
					ArrayList<Chromosome> tempArray = new ArrayList<Chromosome>();
					tempArray.add(subject1);
					return tempArray;
				}
				else{
					pass = tempArrayLevel.get(0); // else this is the level that we need because his kids are one leveled
					randLevel1=0;
				}
			}
			
			if (pass!=null ){ // that means we are not able to do the crossover because there is one kid
				if ((randLevel1+(chromeHash2.size()-randLevel2))<7) // we want our tree not to be too tall
				{
					ArrayList<Node> levelArrayList = tempArrayLevel.get(randLevel1); // get the ones that have double kids
					Node exchangeNode = null;
				
					int randomNodeIndex = (int) Math.round(Math.random()*(levelArrayList.size()-1));
					exchangeNode = levelArrayList.get(randomNodeIndex);
					double randSide = Math.random(); // choose which side to place it
					ArrayList<Node> levelArrayList2 = chromeHash2.get(randLevel2);
					int randomNodeIndex2 = (int) Math.round(Math.random()*(levelArrayList2.size()-1)); // choose the random node from that  ArrayList
					Node exchangedNode2 = levelArrayList2.get(randomNodeIndex2);
					if (randSide>0.5){ // put it on the left side
						exchangeNode.setLeftNode(new Node(exchangedNode2));
					}
					else{
						exchangeNode.setRightNode(new Node(exchangedNode2));
					}
					reIndexChromosone(subject1); // doing seder in the balagan
					break; //finished the crossover
				}

			}
		}
		ArrayList<Chromosome> tempArray = new ArrayList<Chromosome>();
		tempArray.add(subject1);
		return tempArray;
	}
	private void reIndexChromosone(Chromosome chromo){

		chromo.setDfsMap(new HashMap<Integer, ArrayList<Node>>());
		chromo.setTreeLevels(new HashMap<Integer, ArrayList<Node>>());
		chromo.dfs(chromo.getRoot(),0,0);


	}

}
